BMI 作業做得還好嗎?不知道你有沒有完成,但是這邊時間不等人,所以我們就接著聊聊下一個主題吧。
接下要聊聊的是 Python 另一種型別,也就是容器型別。
其實在 JavaScript 中這個型別就是所謂的物件型別,只是在 Python 則是稱為容器型別。
那...什麼是容器型別呢?容器型別你可以把它想像成類似使用一個個的馬克杯或者是盒子,可以用來放各種東西,就如同前面所言以 JavaScript 來講的容器型別就是陣列與物件:
// 陣列 Array
var arr = ['Ray'];
// 物件 Object
var obj = {
name: 'Ray',
};
(這邊要注意陣列依然是屬於物件型別,原因可詳見:JavaScript 核心觀念(31)-物件-陣列)
那麼在 Python 上並不稱為陣列與物件,而是串列(List) 與字典 (Dictionaries):
那麼寫法會不會有差異呢?基本上串列是沒有什麼太大的差異,但是在字典上就會有一點差異:
# 串列
lis = ['Ray']
# 字典
dic = {
'name': 'Ray',
}
為什麼會說字典有一點差異呢?先讓我們轉過來看一下 JavaScript 的部分,在 JavaScript 的物件屬性我們是可以省略單/雙引號的:
var obj = {
name: 'Ray',
};
但是在 Python 是不能省略這個單/雙引號的,否則你是會出現 NameError: name 'name' is not defined
的唷~
那麼由於這個錯誤訊息的關係,代表著沒有使用單/雙引號包覆的這個屬性,是會被 Python 認為這是 一個變數。
因此我們可以大膽的嘗試與挑戰一件事情,假使我宣告了一個變數並且字典的屬性不用使用單/雙引號包覆,其結果又會如何呢?
name = 'myName'
dic = {
name: 'Ray',
}
print(dic) # ??
我們可以看到結果是可以正常運作的:
是不是發現與我們原本的 JavaScript 有些許不同呢?在一般的情況下 JavaScript 是不允許你將物件的屬性變成變數傳入的,不管怎樣都會被 JavaScript 轉換成一個字串屬性,只是在呈現與撰寫上它會忽略並允許你這樣做而已:
var name = 'myName';
var obj = {
name: 'Ray',
};
console.log(obj); // { name: "Ray" }
但是如果真的有這種例外狀況,也就是物件的屬性是必須透過變數所傳入的話,其實也可以做到,這時候你所必須使用是中括號運算子來達到這個需求:
var name = 'myName';
var obj = {
[name]: 'Ray',
};
console.log(obj); // { myName: "Ray" }
See!效果基本上是一樣的,只是變成另一種呈現方式罷了。
接下來就是容器取值,串列取值與字典取值的部分會與原本的 JavaScript 也有差別嗎?先讓我們回顧看一下在 JavaScript 中物件取值與陣列取值的方式:
// 陣列取值
var arr = ['Ray'];
arr[0]; // Ray
var obj = {
name: 'Ray',
};
// 點運算子取值
obj.name; // Ray
// 中括號運算子取值
obj['name'];
// 中括號運算子 + 變數取值
var variable = 'name';
obj[variable]; // Ray
基本上在 JavaScript 中取值的行為主要有兩種方式:
.
[]
那麼在 Python 中也是相同的嗎?如果是的話,那麼應該如何撰寫呢?讓我們看一下範例:
# 字串取值
lis = ['Ray']
lis[0] # 'Ray'
dic = {
'name': 'Ray',
}
dis['name'] # 'Ray'
variable = 'name'
dic[variable] # 'Ray'
你可以發現上面範例我並沒有使用點運算子來取值,原因是因為 Python 無法像 JavaScript 一樣使用點運算子的方式取值,但是 Python 有一些滿特別且好玩的函式方法可以取值,例如 get()
:
dic = {
'name': 'Ray',
}
dic.get('name', 'N/A') # 'Ray'
那這個 get()
語法有何用途呢?主要可以傳入兩個參數,第一個參數是你預計要取值的屬性名稱,第二個則是如果沒有這個屬性名稱存在時要回傳什麼東西給你,舉例來講:
dic = {
'name': 'Ray',
}
dic.get('qq', 'no key') # 'no key'
我們可以發現這種取值方式可以避免當字典的屬性不存在時的錯誤,而且可以客製化錯誤訊息,是不是相當棒呢?
等等,這邊好像一直都沒有提到字典屬性不存在會發生什麼事情對吧?JavaScript 中若我們取一個不存在的物件屬性時,會出現 undefined
,並且還可以繼續執行:
var obj = {};
console.log(obj.myName); // undefined
console.log('我執行囉');
但是在 Python 中則會直接中斷程式碼出現 'KeyError: xxx'
的錯誤訊息:
name = 'myName'
dic = {
name: 'Ray',
}
print(dic[name])
print(dic['qq'])
print('我不能執行了')
好吧,這時候你可能壓力大了,難不成我每次都要先寫好屬性名稱嗎?
難道沒有一種方式是「當這個值不存在時,就寫入一個預設屬性與值」的方式嗎?
答案是有的!
這時候就要使用 setdefault()
這個函式方法,主要也是兩個參數,第一個參數是要設定/取得的屬性名稱,第二個參數則是如果這個屬性不存在時,要預設寫入的值。
舉例來講,假使今天這個屬性不存在時,必須出現「這是一段話
」:
name = 'myName'
dic = {
name: 'Ray',
}
print(dic[name])
print(dic.setdefault('qq', '這是一段話'))
print('我不能執行了')
反之,如果這個屬性已經存在於字典中,那麼它就會走原本本身的值,而不會被覆蓋:
name = 'myName'
dic = {
name: 'Ray',
'qq': '我已經存在囉'
}
print(dic[name])
print(dic.setdefault('qq', '這是一段話'))
print('我不能執行了')
掌握 setdefault
之後你也可以用這個方式去針對 qq
增加一個字典,也就是巢狀物件的概念:
name = 'myName'
dic = {
name: 'Ray',
}
print(dic[name])
print(dic.setdefault('qq', {}))
print(dic['qq'].setdefault('sayHi', 'Hello Ray')) # 也可以寫成 dic.setdefault('qq', {}).setdefault('sayHi', 'Hello Ray')
print('我不能執行了')
相信你已經深深了解到 get()
與 setdefault()
兩者美妙之處,那該選擇哪一個使用就留給你思考囉~
有朋友問我的花雕醉雞卷是如何製作的,所以就順便分享一下材料,基本上就是 200cc 花雕酒、100cc 米酒(我是天味米酒,你可以考慮紅標米酒)、適量的白胡椒就這麼簡單的材料而已,如果你想加入當歸那些也是可以。